#include <iostream>
#include <new>
#include <vector>
#include <exception>
#include <cmath>
#include <limits>
using namespace std;

//template <typename T>//可以同时再定义int n
class Birds
{
protected://后代可看
    double energy = 100.0;
    char* name = NULL;
public:
    const Birds& operator = (const Birds& _obj)
    {
	energy = _obj.energy;
	if (name != NULL)
	    delete [] name;//防止内存泄漏
	name = new char [256];
	for(int i = 0 ;i < 256 ;i++)
	    name[i] = _obj.name[i];
	return *this;
    }
	
	    
    Birds(const Birds& _obj)//复制构造函数
    {
	energy = _obj.energy;
	name = new char [256];//用新的地址存放，避免释放两次相同内存，故不能直接复制指针
	for(int i = 0 ;i < 256 ;i++)
	    name[i] = _obj.name[i];
    }
	    
    Birds()
    {
	cout << "Here comes a bird!" << endl;
	name = new char [256];
	name[0] = 'W';
	name[1] = 'H';
	name[2] = 'Y';
    }
    // virtual void fly() = 0;//纯虚函数，创建概念，必须到具体派生才实现功能//此时birds a会报错
    virtual void sing()
    {
	cout << "JiJi" << endl;
    }
    ~Birds()
    {
	delete [] name;
	cout << "Bird is dying" << endl;
    }
};

class Duck : public Birds//birds用template会报错找不到birds？？//无法看到基类private可看到protected
{
protected:
    double duck_energy = 200.0;
    char* duck_name = NULL;
public:
    Duck()//构造函数：先执行基类，再执行派生类，析构反之
    {
	cout << "Here comes a duck!" << endl;
        duck_name = new char [256];
	duck_name[0] = 'W';
    }
    // void fly(){};
    void sing()
    {
	cout << "gagaga" << endl;
    }
    ~Duck()
    {
	delete [] duck_name;
	cout << "Duck is dying" << endl;//name释放会被释放两次
    }
};
	
int main(int argc, char* argv[])
{
    Birds a;
    Birds b(a);//缺省的复制构造函数会使内存释放两次。进入复制构造函数，没有进入构造函数
    Birds c;
    c = b = a;//缺省的赋值会使内存释放两次，用运算符重载
    Duck d;
    Birds* e = new Duck;//virtual虚函数，指针new到派生功能则用派生功能
    a.sing();
    b.sing();
    c.sing();
    d.sing();
    e->sing();
    return 0;
}
